From 55fda57c44ab90380a92ec36518d572b7d7992b8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Timm=20B=C3=A4der?= Date: Tue, 15 Nov 2016 10:51:41 +0100 Subject: [PATCH] filechooserwidget: Forward file filter to entry And in the entry, apply the currently used filter as a second step to the completion items. https://bugzilla.gnome.org/show_bug.cgi?id=773007 --- gtk/gtkfilechooserentry.c | 95 ++++++++++++++++++++++++++++++++++++-- gtk/gtkfilechooserentry.h | 2 + gtk/gtkfilechooserwidget.c | 6 +++ 3 files changed, 99 insertions(+), 4 deletions(-) diff --git a/gtk/gtkfilechooserentry.c b/gtk/gtkfilechooserentry.c index cc6e119d2a..e5607c1490 100644 --- a/gtk/gtkfilechooserentry.c +++ b/gtk/gtkfilechooserentry.c @@ -32,6 +32,7 @@ #include "gtkwindow.h" #include "gtkintl.h" #include "gtkmarshalers.h" +#include "gtkfilefilterprivate.h" typedef struct _GtkFileChooserEntryClass GtkFileChooserEntryClass; @@ -56,6 +57,7 @@ struct _GtkFileChooserEntry gchar *file_part; GtkTreeModel *completion_store; + GtkFileFilter *current_filter; guint current_folder_loaded : 1; guint complete_on_load : 1; @@ -179,6 +181,83 @@ _gtk_file_chooser_entry_class_init (GtkFileChooserEntryClass *class) G_TYPE_NONE, 0); } +static gboolean +match_func (GtkEntryCompletion *compl, + const gchar *key, + GtkTreeIter *iter, + gpointer user_data) +{ + GtkFileChooserEntry *chooser_entry = user_data; + + /* If we arrive here, the GtkFileSystemModel's GtkFileFilter already filtered out all + * files that don't start with the current prefix, so we manually apply the GtkFileChooser's + * current file filter (e.g. just jpg files) here. */ + if (chooser_entry->current_filter != NULL) + { + char *mime_type = NULL; + gboolean matches; + GFile *file; + GFileInfo *file_info; + GtkFileFilterInfo filter_info; + GtkFileFilterFlags needed_flags; + + file = _gtk_file_system_model_get_file (GTK_FILE_SYSTEM_MODEL (chooser_entry->completion_store), + iter); + file_info = _gtk_file_system_model_get_info (GTK_FILE_SYSTEM_MODEL (chooser_entry->completion_store), + iter); + + /* We always allow navigating into subfolders, so don't ever filter directories */ + if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_REGULAR) + return TRUE; + + needed_flags = gtk_file_filter_get_needed (chooser_entry->current_filter); + + filter_info.display_name = g_file_info_get_display_name (file_info); + filter_info.contains |= GTK_FILE_FILTER_DISPLAY_NAME; + + if (needed_flags & GTK_FILE_FILTER_MIME_TYPE) + { + const char *s = g_file_info_get_content_type (file_info); + if (s != NULL) + { + mime_type = g_content_type_get_mime_type (s); + if (mime_type != NULL) + { + filter_info.mime_type = mime_type; + filter_info.contains |= GTK_FILE_FILTER_MIME_TYPE; + } + } + } + + if (needed_flags & GTK_FILE_FILTER_FILENAME) + { + const char *path = g_file_get_path (file); + if (path != NULL) + { + filter_info.filename = path; + filter_info.contains |= GTK_FILE_FILTER_FILENAME; + } + } + + if (needed_flags & GTK_FILE_FILTER_URI) + { + const char *uri = g_file_get_uri (file); + if (uri) + { + filter_info.uri = uri; + filter_info.contains |= GTK_FILE_FILTER_URI; + } + } + + matches = gtk_file_filter_filter (chooser_entry->current_filter, &filter_info); + + g_free (mime_type); + return matches; + } + + return TRUE; +} + static void _gtk_file_chooser_entry_init (GtkFileChooserEntry *chooser_entry) { @@ -198,9 +277,9 @@ _gtk_file_chooser_entry_init (GtkFileChooserEntry *chooser_entry) /* Need a match func here or entry completion uses a wrong one. * We do our own filtering after all. */ gtk_entry_completion_set_match_func (comp, - (GtkEntryCompletionMatchFunc) gtk_true, - chooser_entry, - NULL); + match_func, + chooser_entry, + NULL); cell = gtk_cell_renderer_text_new (); gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (comp), @@ -546,7 +625,8 @@ populate_completion_store (GtkFileChooserEntry *chooser_entry) { chooser_entry->completion_store = GTK_TREE_MODEL ( _gtk_file_system_model_new_for_directory (chooser_entry->current_folder_file, - "standard::name,standard::display-name,standard::type", + "standard::name,standard::display-name,standard::type," + "standard::content-type", completion_store_set, chooser_entry, N_COLUMNS, @@ -983,3 +1063,10 @@ _gtk_file_chooser_entry_get_local_only (GtkFileChooserEntry *chooser_entry) { return chooser_entry->local_only; } + +void +_gtk_file_chooser_entry_set_file_filter (GtkFileChooserEntry *chooser_entry, + GtkFileFilter *filter) +{ + chooser_entry->current_filter = filter; +} diff --git a/gtk/gtkfilechooserentry.h b/gtk/gtkfilechooserentry.h index cf7d8504ba..732a87a741 100644 --- a/gtk/gtkfilechooserentry.h +++ b/gtk/gtkfilechooserentry.h @@ -46,6 +46,8 @@ void _gtk_file_chooser_entry_select_filename (GtkFileChooserEnt void _gtk_file_chooser_entry_set_local_only (GtkFileChooserEntry *chooser_entry, gboolean local_only); gboolean _gtk_file_chooser_entry_get_local_only (GtkFileChooserEntry *chooser_entry); +void _gtk_file_chooser_entry_set_file_filter (GtkFileChooserEntry *chooser_entry, + GtkFileFilter *filter); G_END_DECLS diff --git a/gtk/gtkfilechooserwidget.c b/gtk/gtkfilechooserwidget.c index 6a270ff196..d0b72864bc 100644 --- a/gtk/gtkfilechooserwidget.c +++ b/gtk/gtkfilechooserwidget.c @@ -2610,6 +2610,8 @@ location_entry_setup (GtkFileChooserWidget *impl) _gtk_file_chooser_entry_set_local_only (GTK_FILE_CHOOSER_ENTRY (priv->location_entry), priv->local_only); _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (priv->location_entry), priv->action); + _gtk_file_chooser_entry_set_file_filter (GTK_FILE_CHOOSER_ENTRY (priv->location_entry), + priv->current_filter); gtk_entry_set_width_chars (GTK_ENTRY (priv->location_entry), 45); gtk_entry_set_activates_default (GTK_ENTRY (priv->location_entry), TRUE); } @@ -7669,6 +7671,10 @@ filter_combo_changed (GtkComboBox *combo_box, new_index = gtk_combo_box_get_active (combo_box); new_filter = g_slist_nth_data (priv->filters, new_index); set_current_filter (impl, new_filter); + + if (priv->location_entry != NULL) + _gtk_file_chooser_entry_set_file_filter (GTK_FILE_CHOOSER_ENTRY (priv->location_entry), + new_filter); } static void -- 2.30.2